package org.example.rowing.controller.raceProcessController;

import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import lombok.extern.slf4j.Slf4j;
import org.example.rowing.controller.CKRegistrationExportController;
import org.example.rowing.controller.LaneExportController;
import org.example.rowing.controller.util.NavigationUtil;
import org.example.rowing.domain.RegistrationWithAthlete;
import org.example.rowing.domain.RoundScore;
import org.example.rowing.domain.Team;
import org.example.rowing.service.*;
import org.example.rowing.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.*;

@Controller
@Slf4j
public class LessSixController {
    @FXML
    public Button nextRoundButton;
    @FXML
    public Button randomButton;
    @FXML
    public Button exportLaneButton;
    @FXML
    private Label p1, p2, p3, p4, p5, p6; // 显示预赛队伍的Label
    @FXML
    private Label f1, f2, f3, f4, f5, f6; // 显示决赛队伍的Label
    @FXML
    private Label rank1, rank2, rank3, rank4, rank5 ,rank6;

    private Long raceId;
    private RaceVO raceVO;
    Map<String, Label> labelMap = new HashMap<>();
    /**
     * 预赛队伍列表
     */
    private Set<RoundScoreVO> pSet = new HashSet<>();
    private Set<RoundScoreVO> fSet = new HashSet<>();
    // 新增：标识抽签是否完成
    private boolean lotteryDone;
    private Integer pListLength;
    private final Object rankingLock = new Object();

    @Autowired
    private RaceProcessCommonService raceProcessCommonService;
    @Autowired
    private RaceInfoService raceInfoService;
    @Autowired
    private ProcessLessSixBoatsService processLessSixBoatsService;
    @Autowired
    private DrawLotteryService drawLotteryService;

    public static final List<String> teamLanes = Arrays.asList("", "A组3号", "A组4号", "A组2号", "A组5号", "A组1号", "A组6号");


    // 双击矩形区域显示分数输入框
    @FXML
    public void initialize(RaceVO raceVO) {
        this.raceId = raceVO.getId();
        this.raceVO = raceVO;
        this.lotteryDone = false;
        log.info("raceId---------------------------: {}", raceId);

        Map<RegistrationVO, String> lotteryResult = drawLotteryService.getLotteryResult(raceId);
        if (lotteryResult != null && !lotteryResult.isEmpty()) {
            lotteryDone = true;
        }

        List<RegistrationVO> registrationVOS = raceProcessCommonService.getRegistrationVOS(raceVO);
        pListLength = registrationVOS.size();

        labelMap.clear();
        labelMap.put("p1", p1);
        labelMap.put("p2", p2);
        labelMap.put("p3", p3);
        labelMap.put("p4", p4);
        labelMap.put("p5", p5);
        labelMap.put("p6", p6);
        labelMap.put("f1", f1);
        labelMap.put("f2", f2);
        labelMap.put("f3", f3);
        labelMap.put("f4", f4);
        labelMap.put("f5", f5);
        labelMap.put("f6", f6);

        for (int i = 0; i < pListLength; i++) {
            for (String key : labelMap.keySet()) {
                if (key.contains(String.valueOf(i + 1))) {
                    if (key.startsWith("f")) {
                        labelMap.get(key).setOnMouseClicked(this::handleRectangleClick);
                    } else {
                        labelMap.get(key).setUserData(new RoundScoreVO());
                        RegistrationVO registrationVO = registrationVOS.get(i);
                        labelMap.get(key).setText(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId());
                        labelMap.get(key).setOnMouseClicked(this::handleRectangleClick);
                    }
                }
            }
        }

        // 恢复分数信息
        pSet.clear();
        fSet.clear();
        List<RoundScoreVO> roundScoreVOS = raceInfoService.loadRoundScoreVOByRaceId(raceId);
        for (RoundScoreVO roundScoreVO : roundScoreVOS) {
            String labelId = roundScoreVO.getLabelId();
            if (labelId == null) {
                continue;
            }
            Label label = findLabelById(labelId);
            String labelText = "";
            if (roundScoreVO.getScore() != null) {
                if (roundScoreVO.getStatus().equals("NORMAL")) {
                    double time = roundScoreVO.getScore();
                    String formattedTime = getFormattedTime(time);
                    labelText = " 用时：" + formattedTime;
                } else {
                    labelText = " " + roundScoreVO.getStatus();
                }
            }
            String text = roundScoreVO.getRegistrationVO().getTeam().getName() + "-" + roundScoreVO.getRegistrationVO().getRegistrationId();
            label.setText(text + labelText);
            label.setUserData(roundScoreVO);
            Tooltip tooltip = new Tooltip(text + labelText);
            tooltip.setShowDelay(javafx.util.Duration.millis(500));
            label.setTooltip(tooltip);
            if (roundScoreVO.getScore() != null) {
                if (labelId.startsWith("p")) {
                    pSet.add(roundScoreVO);
                } else if (labelId.startsWith("f")) {
                    fSet.add(roundScoreVO);
                }
            }
        }
    }

    private static String getFormattedTime(double time) {
        int minutes = (int) (time / 60);
        int seconds = (int) (time % 60);
        int hundredths = (int) ((time * 100) % 100);
        return String.format("%d:%02d.%02d", minutes, seconds, hundredths);
    }

    // 根据 labelId 找到对应的 Label
    private Label findLabelById(String labelId) {
        switch (labelId) {
            case "p1": return p1;
            case "p2": return p2;
            case "p3": return p3;
            case "p4": return p4;
            case "p5": return p5;
            case "p6": return p6;
            case "f1": return f1;
            case "f2": return f2;
            case "f3": return f3;
            case "f4": return f4;
            case "f5": return f5;
            case "f6": return f6;
            case "rank1": return rank1;
            case "rank2": return rank2;
            case "rank3": return rank3;
            case "rank4": return rank4;
            case "rank5": return rank5;
            case "rank6": return rank6;
            default: return null;
        }
    }

    // 处理矩形区域的双击事件
    private void handleRectangleClick(MouseEvent event) {
        if (event.getClickCount() == 2) {  // 双击事件
            Label source = (Label) event.getSource();
            log.info("当前双击事件为：{}", source);

            // 必须先完成抽签
            if (!lotteryDone) {
                showErrorDialog("请先完成抽签，再输入预赛成绩！");
                return;
            }

            if (source != null) {
                // 弹出输入框，让用户输入分数
                ScoreInputResult  scoreInputResult = promptForTime();
                RoundScoreVO roundScoreVO = (RoundScoreVO) source.getUserData();
                if (scoreInputResult != null && roundScoreVO != null) {
                    roundScoreVO.setStatus(scoreInputResult.getStatus());
                    String text = roundScoreVO.getRegistrationVO().getTeam().getName() + "-" + roundScoreVO.getRegistrationVO().getRegistrationId();

                    if ("NORMAL".equals(scoreInputResult.getStatus())) {
                        roundScoreVO.setScore(scoreInputResult.getTime());
                        // 格式化为 x1:x2.x3 格式显示
                        String formattedTime = getFormattedTime(scoreInputResult.getTime());
                        source.setText(text + " 用时：" + formattedTime);
                        Tooltip tooltip = new Tooltip(text + " 用时：" + formattedTime);
                        tooltip.setShowDelay(javafx.util.Duration.millis(500));
                        source.setTooltip(tooltip);
                    } else {
                        roundScoreVO.setScore(Double.MAX_VALUE);
                        // 格式化为 x1:x2.x3 格式显示
                        source.setText(text + " " + scoreInputResult.getStatus());
                        Tooltip tooltip = new Tooltip(text + " " + scoreInputResult.getStatus());
                        tooltip.setShowDelay(javafx.util.Duration.millis(500));
                        source.setTooltip(tooltip);
                    }

                    // 保存用户输入的分数
                    raceInfoService.saveRoundScore(roundScoreVO);
                    if (roundScoreVO.getScore() != null) {
                        if (source.getId().startsWith("p")) {
                            pSet.add(roundScoreVO);
                        } else if (source.getId().startsWith("f")) {
                            fSet.add(roundScoreVO);
                        }
                    }
                }
            }
        }
    }

    // 自定义时间输入对话框
    private ScoreInputResult promptForTime() {
        Dialog<ScoreInputResult> dialog = new Dialog<>();
        dialog.setTitle("比赛用时／状态");
        dialog.setHeaderText("输入用时或直接选择状态");

        // OK / Cancel buttons
        ButtonType ok = new ButtonType("确认", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(ok, ButtonType.CANCEL);

        // layout: status combo + time fields
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        // status selector
        ComboBox<String> statusCombo = new ComboBox<>();
        statusCombo.getItems().addAll("NORMAL", "DNS", "DNF", "DSQ");
        statusCombo.setValue("NORMAL");

        TextField minutesField    = new TextField();
        TextField secondsField    = new TextField();
        TextField hundredthsField = new TextField();
        minutesField.setPromptText("分钟");
        secondsField.setPromptText("秒");
        hundredthsField.setPromptText("百分秒");

        grid.add(new Label("状态:"), 0, 0);
        grid.add(statusCombo,    1, 0);
        grid.add(new Label("分钟:"),   0, 1);
        grid.add(minutesField,   1, 1);
        grid.add(new Label("秒:"),      0, 2);
        grid.add(secondsField,   1, 2);
        grid.add(new Label("百分秒:"), 0, 3);
        grid.add(hundredthsField,1, 3);

        dialog.getDialogPane().setContent(grid);

        // when status ≠ NORMAL, disable the time inputs
        statusCombo.valueProperty().addListener((obs, old, val) -> {
            boolean timeNeeded = "NORMAL".equals(val);
            minutesField.setDisable(!timeNeeded);
            secondsField.setDisable(!timeNeeded);
            hundredthsField.setDisable(!timeNeeded);
        });

        // validation: if NORMAL, require time fields valid; else enable OK immediately
        Node confirm = dialog.getDialogPane().lookupButton(ok);
        BooleanBinding timeValid = Bindings.createBooleanBinding(() -> {
            return minutesField.getText().matches("\\d+") &&
                    secondsField.getText().matches("\\d{1,2}") &&
                    hundredthsField.getText().matches("\\d{1,2}") &&
                    Integer.parseInt(secondsField.getText()) < 60 &&
                    Integer.parseInt(hundredthsField.getText()) < 100;
        }, minutesField.textProperty(), secondsField.textProperty(), hundredthsField.textProperty());

        confirm.disableProperty().bind(
                Bindings.when(statusCombo.valueProperty().isEqualTo("NORMAL"))
                        .then(timeValid.not())
                        .otherwise(false)
        );

        // convert result
        dialog.setResultConverter(btn -> {
            if (btn == ok) {
                String status = statusCombo.getValue();
                if (!"NORMAL".equals(status)) {
                    // for DNS/DNF/DSQ, we treat score as MAX_VALUE
                    return new ScoreInputResult(Double.MAX_VALUE, status);
                } else {
                    int m = Integer.parseInt(minutesField.getText());
                    int s = Integer.parseInt(secondsField.getText());
                    int h = Integer.parseInt(hundredthsField.getText());
                    double total = m * 60.0 + s + h / 100.0;
                    return new ScoreInputResult(total, "NORMAL");
                }
            }
            return null;
        });

        return dialog.showAndWait().orElse(null);
    }

    public void handleNextRoundClick(ActionEvent event) {
        synchronized(rankingLock) {
            log.info("处理下一轮 | 预赛集大小: {} | 决赛集大小: {} | 线程: {}",
                    pSet.size(), fSet.size(),
                    Thread.currentThread().getName());
            List<RoundScoreVO> pRounds = new ArrayList<>(pSet);
            List<RoundScoreVO> fRounds = new ArrayList<>(fSet);
            // 对所有队伍按分数进行排序
            if (fRounds.size() == pListLength) {
                // 处理决赛
                log.info("决赛队伍：{}", fRounds);
                List<RoundScoreVO> rank = processLessSixBoatsService.getRank(fRounds, raceVO);
                for (int i = 0; i < rank.size(); i++) {
                    Label labelById = findLabelById("rank" + (i + 1));
                    String text = rank.get(i).getRegistrationVO().getTeam().getName() + "-" + rank.get(i).getRegistrationVO().getRegistrationId();
                    labelById.setText(text);
                    Tooltip tooltip = new Tooltip(text);
                    tooltip.setShowDelay(javafx.util.Duration.millis(500));
                    labelById.setTooltip(tooltip);
                }
            } else if (pRounds.size() == pListLength) {
                // 处理预赛
                log.info("预赛队伍：{}", pRounds);
                // 处理预赛：按分数降序排列
                List<RoundScoreVO> advancingToFinals = processLessSixBoatsService.getAdvancingToFinals(pRounds);

                advancingToFinals = raceProcessCommonService.orderOptimization(pRounds, advancingToFinals);

                // 更新决赛的队伍
                for (int i = 0; i < advancingToFinals.size(); i++) {
                    RoundScoreVO vo = advancingToFinals.get(i);
                    RegistrationVO registrationVO = vo.getRegistrationVO();
                    Label label = findLabelById("f" + (i + 1));

                    RoundScoreVO roundScore = new RoundScoreVO(raceId, registrationVO, "决赛", label.getId(), teamLanes.get(i + 1), null);
                    if (vo.getStatus().equals("NORMAL")) {
                        label.setText(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId());
                        Tooltip tooltip = new Tooltip(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId());
                        tooltip.setShowDelay(javafx.util.Duration.millis(500));
                        label.setTooltip(tooltip);
                        label.setUserData(roundScore);
                    } else {
                        label.setText(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId() + " " + vo.getStatus());
                        Tooltip tooltip = new Tooltip(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId() + " " + vo.getStatus());
                        tooltip.setShowDelay(javafx.util.Duration.millis(500));
                        label.setTooltip(tooltip);
                        roundScore.setScore(Double.MAX_VALUE);
                        roundScore.setStatus(vo.getStatus());
                        label.setUserData(roundScore);
                        fSet.add(roundScore);
                    }
                    raceInfoService.saveRoundScore(roundScore);
                }
            } else {
                showErrorDialog("当前比赛未结束，无法晋级下一轮。请输入当前比赛的所有成绩！");
            }
            // 更新赛制和分数显示
            log.info("晋级信息已更新");
        }
    }

    public void handleRandomClick(ActionEvent event) {
        log.info("进入抽签: {}", event.getSource());
        NavigationUtil.showPopup(
                "/fxml/rowingViews/raceProcessView/randomView.fxml",
                "查看抽签",
                randomButton.getScene().getWindow(),
                controller -> {
                    if (controller instanceof DrawLotteryController drawLotteryController) {
                        drawLotteryController.setConfirmCallback(this::updateLotteryResult);
                        drawLotteryController.initialize(raceId);
                    }
                }
        );
    }

    /**
     * 根据抽签结果更新预赛区域各标签的队伍名称。
     * 抽签结果为 Map<teamName, lane>，需根据预先约定的航道顺序更新对应标签。
     */
    private void updateLotteryResult(Map<RegistrationVO, String> lotteryResult) {
        // 构建航道 → 标签映射
        Map<String, Label> laneToLabel = new HashMap<>();
        laneToLabel.put("A组2号", p3);
        laneToLabel.put("A组3号", p1);
        laneToLabel.put("A组4号", p2);
        laneToLabel.put("A组5号", p4);
        laneToLabel.put("A组1号", p5);
        laneToLabel.put("A组6号", p6);

        for (Map.Entry<RegistrationVO, String> entry : lotteryResult.entrySet()) {
            String lane = entry.getValue();
            RegistrationVO registrationVO = entry.getKey();
            Label label = laneToLabel.get(lane);
            label.setText(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId());
            Tooltip tooltip = new Tooltip(registrationVO.getTeam().getName() + "-" + registrationVO.getRegistrationId());
            tooltip.setShowDelay(javafx.util.Duration.millis(500));
            label.setTooltip(tooltip);

            RoundScoreVO roundScoreVOCondition = new RoundScoreVO();
            roundScoreVOCondition.setRegistrationId(registrationVO.getRegistrationId());
            roundScoreVOCondition.setRaceId(raceId);
            roundScoreVOCondition.setRound("预赛");
            List<RoundScoreVO> roundScoreVOS = raceInfoService.showRoundScoreByCondition(roundScoreVOCondition);
            RoundScoreVO roundScoreVO = roundScoreVOS.get(0);
            roundScoreVO.setLabelId(label.getId());
            label.setUserData(roundScoreVO);
            raceInfoService.saveRoundScore(roundScoreVO);
        }
        log.info("根据抽签结果更新后的预赛队伍顺序：{}", lotteryResult);
        lotteryDone = true;
    }


    // 弹出错误提示框
    private void showErrorDialog(String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle("输入错误");
        alert.setHeaderText(null);
        alert.setContentText(message);
        alert.showAndWait();
    }

    @FXML
    public void handleExportLaneEvent(ActionEvent event) {
        // 打开添加赛事界面的逻辑
        log.info("开始选择导出项目");
        NavigationUtil.showPopup(
                NavigationUtil.viewMap.get(exportLaneButton.getId()),
                "选择导出确认单的队伍",
                exportLaneButton.getScene().getWindow(),
                controller -> {
                    if (controller instanceof LaneExportController) {
                        ((LaneExportController) controller).initialize(raceId);
                    }
                }
        );
    }
}
